#include <sys_config.h>

//#ifdef SHOW_PICS
//#if(SHOW_PICS == SHOW_SINGLE_PIC)
#ifdef PIP_PNG_GIF

#include <basic_types.h>
#include <mediatypes.h>
#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <hld/hld_dev.h>
#include <hld/ge/ge.h>
#include <hld/osd/osddrv_dev.h>
#include <api/libimagedec/imagedec.h>
#include <hld/dis/vpo.h>

//#include "test_jpg.h"
#include <api/libfs2/stdio.h>
#include "ad_pic_gfx.h"
#include "ad_pic_img.h"
//#include "imagedec_osd.h"
//#include "imagedec_main.h"

//#define AD_IMG_DEBUG
#ifdef AD_IMG_DEBUG
#define AD_IMG_PRINTF	libc_printf
#else
#define AD_IMG_PRINTF(...)	do{}while(0)
#endif


static UINT8 *img_file_addr; //start address of the buffer to restore the image file
static UINT32 img_file_size;  // image file size
static INT32 img_input_pos = 0;

static int img_read_data(UINT32 fh,BYTE *buf, UINT32 size)
{
	UINT32 read_pos;
	UINT32 read_len;

	read_pos = img_input_pos+size;
	if(read_pos>img_file_size)
	{
		read_len = img_file_size-img_input_pos;
		MEMCPY((void *)buf, (void *)(img_file_addr+img_input_pos), read_len);
		img_input_pos += read_len;
		return read_len;
	}
	else
	{
		MEMCPY((void *)buf, (void *)(img_file_addr+img_input_pos), size);
		img_input_pos+=size;
		return size;
	}
}

static int img_seek_data(UINT32 fh,long offset, UINT32 origin)
{
	if(origin == 0)
	{
		img_input_pos = (UINT32)offset;
		return TRUE;
	}
	return FALSE;
}

static void ad_pic_img_blt(void *handle, pImagedec_Out_Image pimage, struct OSDRect *rect)
{
	ad_pic_gfx_draw(rect, (UINT8 *)pimage->start_buf);
}
#if 0
//-----
#define OUT_PUT_AYCBCR8888
extern Imagedec_hdl g_imagedec_hdl[IMAGEDEC_MAX_INSTANCE];
extern  imagedec_osd_ins g_imagedec_osd_ins;

static INT32 Y = 0, Cb = 0, Cr = 0;
static INT32 Y_2 = 0,Cr_R = 0, Cr_G = 0, Cb_G = 0, Cb_B = 0;
static INT32  Red = 0, Green = 0, Blue = 0;
static UINT16  RGB; //16bits
#if 0
IMAGEDEC_INLINE void YUVTORGB()
{
	Red = Y + ((Cr * YUVTOR_PAR)>>16);
	Green = Y - ((Cr * YUVTOG_PAR_R)>>16) - ((Cb * YUVTOG_PAR_U)>>16);
	Blue = Y + ((Cb * YUVTOB_PAR)>>16);
	Red = Red < 0 ? 0 :(Red > 0xFF ? 0xFF : Red);
	Green = Green < 0 ? 0 :(Green > 0xFF ? 0xFF : Green);
	Blue = Blue < 0 ? 0 :(Blue > 0xFF ? 0xFF : Blue);
	RGB = (UINT16)(0x8000 | ((Red<<7) & 0x7C00) | ((Green<<2) & 0x3E0)  | (Blue>>3));
}
#endif
#define YUVTORGB_TRANSFER_YUV	{		\
		Y = Y < 16 ? 16 : (Y > 235 ? 235 : Y);	\
		Y -= 16;	\
		Y_2 = (Y * YUVTOY_PAR)>>16;	\
		Cb = Cb < 16 ? 16 : (Cb > 240 ? 240 : Cb);	 \
		Cr = Cr < 16 ? 16 : (Cr > 240 ? 240 : Cr);	\
		Cb -= 128;	\
		Cr -= 128;	\
		Cr_R = (Cr * YUVTOR_PAR)>>16;	\
		Cr_G = (Cr * YUVTOG_PAR_R)>>16;	\
		Cb_G = (Cb * YUVTOG_PAR_U)>>16;	\
		Cb_B = (Cb * YUVTOB_PAR)>>16;	\
	}

#define YUVTORGB_GEN_RGB		{		\
		Red = Y + Cr_R;	\
		Green = Y - Cr_G - Cb_G;	\
		Blue = Y + Cb_B;	\
		Red = Red < 0 ? 0 :(Red > 0xFF ? 0xFF : Red);		\
		Green = Green < 0 ? 0 :(Green > 0xFF ? 0xFF : Green);		\
		Blue = Blue < 0 ? 0 :(Blue > 0xFF ? 0xFF : Blue);		\
		RGB = (UINT16)(0x8000 | ((Red>>3)<<10) | ((Green>>3)<<5)  | (Blue>>3));\
	}
static void update(void *ins)
{
	pImagedec_hdl phdl = &g_imagedec_hdl[0];
	Imagedec_Out_Image image;
	pimagedec_osd_out pout = &(((pimagedec_osd_ins)ins)->out);
	pimagedec_osd_raw_pic ppic = &(((pimagedec_osd_ins)ins)->pic);
	UINT8 *y_buf = ppic->y_buf;
	UINT8 *c_buf = ppic->c_buf;
#ifdef OUT_PUT_AYCBCR8888
	UINT32 *bitmap = (UINT32 *)((pout->bitmap + 3) & 0xFFFFFFFC);
#else
	UINT16 *bitmap = (UINT16 *)((pout->bitmap + 1) & 0xFFFFFFFE);
#endif
	UINT32 y_line = 0, c_line = 0;
	UINT32 bit_line = 0;
	UINT16 w = 0, h = 0;
	UINT16 i = 0,j = 0;
	UINT8 flag = 0;

	UINT32 MB_LINE_SIZE = 0;

	MEMSET((void *)&image,0,sizeof(Imagedec_Out_Image));

	pout->bitmap = (UINT32)bitmap;

	if((pout->stride * ppic->height) > pout->buf_size)
	{
		jpeg_printf("Don't have enough bitmap buf\n");
		terminate(JPGD_OSD_NO_ENOUGH_BITMAP_BUF);
	}

	w = (ppic->width < pout->dis_rect.uWidth) ? ppic->width : pout->dis_rect.uWidth;
	h = (ppic->height < pout->dis_rect.uHeight) ? ppic->height : pout->dis_rect.uHeight;

	w &= ~1;
	h &= ~1;

#ifdef OUT_PUT_AYCBCR8888
	pout->stride = pout->dis_rect.uWidth<<2;
#else
	pout->stride = pout->dis_rect.uWidth<<1;
#endif

	pout->dis_rect.uWidth = w;
	pout->dis_rect.uHeight = h;

	if((0 == w) || (0 == h))
		terminate(JPGD_OSD_SHOW_RECT_FAIL);

	MEMSET((void *)bitmap,0,pout->buf_size);

#ifdef OUT_PUT_AYCBCR8888
	MB_LINE_SIZE = (ppic->stride<<4) - 512;
#else
	MB_LINE_SIZE = (ppic->stride<<4) - 256;
#endif

	y_line = (UINT32)y_buf;
	c_line = (UINT32)c_buf;
	bit_line = (UINT32)bitmap;
	// osal_cache_flush((void *)y_buf,ppic->y_size);
	// osal_cache_flush((void *)c_buf,ppic->c_size);
	for(i = 0;i < h;i++)
	{
		for(j = 0;j < w;j++)
		{
			Y = (INT32)*y_buf++;
#ifdef OUT_PUT_AYCBCR8888
			if(0x1F == (j &0x1F))
				y_buf += 480;
#else
			if(0xF == (j &0xF))
				y_buf += 240;
#endif

			if(0 == (j & 0x1))
			{
#ifdef OUT_PUT_AYCBCR8888
				if(0x1E == (j & 0x1F))
#else
				if(0xE == (j & 0xF))
#endif
					flag = 1;
				else
					flag = 0;
				Cb = (INT32)*c_buf++;
				Cr = (INT32)*c_buf++;
				if(flag)
#ifdef OUT_PUT_AYCBCR8888
					c_buf += 480;
#else
					c_buf += 240;
#endif

#ifdef OUT_PUT_AYCBCR8888

#else
				YUVTORGB_TRANSFER_YUV;
#endif
			}
#ifdef OUT_PUT_AYCBCR8888

#else
			YUVTORGB_GEN_RGB;
#endif

#ifdef OUT_PUT_AYCBCR8888
			*bitmap++ = 0xFF000000 | (Cr<<16) | (Y<<8) | Cb;
#else
			*bitmap++ = RGB;
#endif
		}

		bit_line += pout->stride;

#ifdef OUT_PUT_AYCBCR8888
		bitmap = (UINT32 *)bit_line;
#else
		bitmap = (UINT16 *)bit_line;
#endif

#ifdef OUT_PUT_AYCBCR8888
		y_line += 32;
#else
		y_line += 16;
#endif
		if(1 == (i & 0x1))
		{
#ifdef OUT_PUT_AYCBCR8888
			c_line += 32;
#else
			c_line += 16;
#endif
			if(0xF == (i & 0xF))
			{
				y_line += MB_LINE_SIZE;
				if(0x1F == (i & 0x1F))
					c_line += MB_LINE_SIZE;
			}
		}
		y_buf = (UINT8 *)y_line;
		c_buf = (UINT8 *)c_line;
	}

	// output the image by the blt call back function. only support 16Bits OSD
	image.bpp = 16;
	image.start_buf = pout->bitmap;
	image.stride = pout->stride;
	image.width = w;
	image.height = h;
	jpeg_printf("osd update: buf %x stride %d width %d height %d\n",image.start_buf
		,image.stride,image.width,image.height);

	if(NULL != pout->blt)
		pout->blt(pout->handle,&image,&pout->dis_rect);
}

void imagedec_osd_init(pImagedec_Osd_Config config)
{
	MEMSET((void *)&g_imagedec_osd_ins,0,sizeof(imagedec_osd_ins));

	g_imagedec_osd_ins.out.handle= config->handle;
	g_imagedec_osd_ins.out.frmt = config->pic_frmt;
	g_imagedec_osd_ins.out.blt = config->blt;
	g_imagedec_osd_ins.update_osd = update;
}
#endif
//-----
 //the parameter of rect is the showing region on GE
static INT32 ad_pic_img_dec(struct OSDRect *rect)
{
	imagedec_id id = 0;
	UINT32 file_handle = 0xFF;
	BOOL ret = 0;
    imagedec_release(1);
	Imagedec_Init_Config img_init_info;
	MEMSET(&img_init_info,0,sizeof(Imagedec_Init_Config));
	img_init_info.frm_y_size = __MM_FB0_Y_LEN;
	img_init_info.frm_y_addr = __MM_FB0_Y_START_ADDR;
	img_init_info.frm_c_size = __MM_FB0_C_LEN;
	img_init_info.frm_c_addr = __MM_FB0_C_START_ADDR;
	img_init_info.frm2_y_size = __MM_FB1_Y_LEN;
	img_init_info.frm2_y_addr = __MM_FB1_Y_START_ADDR;
	img_init_info.frm2_c_size = __MM_FB1_C_LEN;
	img_init_info.frm2_c_addr = __MM_FB1_C_START_ADDR;
	img_init_info.frm3_y_size = __MM_FB2_Y_LEN;
	img_init_info.frm3_y_addr = __MM_FB2_Y_START_ADDR;
	img_init_info.frm3_c_size = __MM_FB2_C_LEN;
	img_init_info.frm3_c_addr = __MM_FB2_C_START_ADDR;
	img_init_info.frm_mb_type = 0;
#ifdef DUAL_ENABLE	
	img_init_info.decoder_buf = (UINT8 *)((__MM_MP_BUFFER_ADDR+0x10000) & ~(3<<29));//__MM_IMG_DEC_ADDR;
#else
    img_init_info.decoder_buf = (UINT8 *)((__MM_TTX_BS_START_ADDR+__MM_TTX_BS_LEN + 0x10000)  & ~(3<<29));
#endif		
	img_init_info.decoder_buf_len = 0x400000;//0x54600; //0x7E800;//0x3FA40; // 0x3FA40=320*240*1.5+0x20000 ;0x15180=320*240//__MM_IMG_DEC_LEN;
	img_init_info.fread_callback = img_read_data;
	img_init_info.fseek_callback = img_seek_data;
	id = imagedec_init(&img_init_info);
    AD_IMG_PRINTF("%s() imagedec_init id = (%d)!\n", __FUNCTION__, id);
	if(0 == id)
	{
		AD_IMG_PRINTF("%s() imagedec_init failed(%d)!\n", __FUNCTION__, id);
		return !SUCCESS;
	}


#ifdef DUAL_ENABLE
        ret = imagedec_ioctl_ex(id, IMAGEDEC_IO_CMD_OPEN_HW_ACCE, 0);
#else
	ret = imagedec_ioctl(id, IMAGEDEC_IO_CMD_OPEN_HW_ACCE, 0);
#endif
        if(TRUE != ret)
	{
		AD_IMG_PRINTF("%s() imagedec_ioctl(IMAGEDEC_IO_CMD_OPEN_HW_ACCE) failed!\n", __FUNCTION__);
		return !SUCCESS;
	}

	Imagedec_Osd_Config config;
	MEMSET((void *)&config, 0, sizeof(Imagedec_Osd_Config));
	config.blt = ad_pic_img_blt;
	config.handle = 0;//(void *)ad_pic_get_ge_surface(AD_DST_SURFACE);
	config.pic_frmt = 0;
	imagedec_osd_init(&config);

	Imagedec_Mode_Par dec_par;
	MEMSET((void *)&dec_par,0,sizeof(Imagedec_Mode_Par));
	dec_par.vp_close_control = 0;
	dec_par.pro_show = 1;
 	dec_par.dis_rect.uStartX = 0; //rect->uLeft;
	dec_par.dis_rect.uStartY = 0;
	dec_par.dis_rect.uWidth = 720; //rect->uWidth;
	dec_par.dis_rect.uHeight = 576; // rect->uHeight;
	dec_par.src_rect.uStartX = 0; //rect->uLeft;
	dec_par.src_rect.uStartY = 0;
	dec_par.src_rect.uWidth = 720; //rect->uWidth;
	dec_par.src_rect.uHeight = 576; //rect->uHeight;
	imagedec_set_mode(1, 1, &dec_par);

	Imagedec_Osd_Io_Cmd cmd;
	MEMSET((void *)&cmd,0,sizeof(Imagedec_Osd_Io_Cmd));
	cmd.on = 1;
#ifdef DUAL_ENABLE
	cmd.bitmap_start = (UINT8 *)((__MM_MP_BUFFER_ADDR+0x410000/*0x64600*/)& ~(3<<29)); //__MM_IMG_BITMAP_ADDR;
#else
    cmd.bitmap_start = img_init_info.decoder_buf + 0x410000;
#endif		
	cmd.bitmap_size = 0x400000;//0x2A300; //0x2A300= 320*240*2 //__MM_IMG_BITMAP_LEN;
//for testing, remember to delete the malloc size
//	cmd.bitmap_start = (UINT8 *)(MALLOC(0x2A300));
//	cmd.bitmap_size = 0x2A300; //0x2A300= 320*240*2 //__MM_IMG_BITMAP_LEN;

	cmd.dis_rect.uStartX = rect->uLeft;
	cmd.dis_rect.uStartY = 0;  //rect->uTop;
	cmd.dis_rect.uWidth = rect->uWidth;
	cmd.dis_rect.uHeight = rect->uHeight;

#ifdef DUAL_ENABLE
        imagedec_ioctl_ex(id, IMAGEDEC_IO_CMD_OSD_SHOW, (UINT32)&cmd);
#else
        imagedec_ioctl(id, IMAGEDEC_IO_CMD_OSD_SHOW, (UINT32)&cmd);
#endif

	img_input_pos = 0;
	AD_IMG_PRINTF("----ret111=%d",ret);
	ret = imagedec_decode(id, file_handle);
	AD_IMG_PRINTF("----ret=%d",ret);
    if(ret!=TRUE)
        AD_IMG_PRINTF("\n Decode Image Unsuccessfully");

	if(imagedec_stop(id)!=TRUE)
        AD_IMG_PRINTF("\n Stop Image decoding unsuccessfully!\n");
	if(imagedec_release(id)!=TRUE)
        AD_IMG_PRINTF("\n Release Image decoder unsuccessfully!\n");
}

INT32 ad_pic_img_draw(UINT8* file, UINT32 file_len, struct OSDRect *rect)
{
    img_input_pos = 0;
	img_file_addr = (UINT8*)file;
	img_file_size = file_len;

	ad_pic_img_dec(rect);

	return SUCCESS;
}

void ad_pic_img_close(void)
{
   AD_IMG_PRINTF("\n Close the IMG AD \n");
}


const char test_sample[]={};
static ad jpg_file[2] =
{
    {
		0,
		(UINT8 *)test_sample,
		sizeof(test_sample),
		{0,0,720,576}
	},
    /*
	{
		0,
		(UINT8 *)test0_jpg,
		sizeof(test0_jpg),
		{0,0,720,576}
	},
	{
		1,
		(UINT8 *)test1_jpg,
		sizeof(test1_jpg),
		{0,0,720,576}
	},
	/*{
		2,
		(UINT8 *)test2_jpg,
		sizeof(test2_jpg),
		{0,0,720,576}
	},*/
};
void show_jpg_pic(UINT8 num)
{
	ad *ad = NULL;
	struct sto_device *sto_flash_dev;
	UINT8 *logo_buf;
	UINT32 addr,len;
#if 0
	if(api_get_chunk_add_len(0x0AF50300,&addr,&len) == 0) 	//jpg chunk id
	{
        AD_IMG_PRINTF("api_get_chunk_add_len error.\n");
        return;
	}
	logo_buf = (UINT8 *)MALLOC(len);
	sto_flash_dev = (struct sto_device *)dev_get_by_id(HLD_DEV_TYPE_STO, 0);
	sto_get_data(sto_flash_dev, (UINT8 *)logo_buf, addr, len);

	num %= (sizeof(jpg_file)/sizeof(ad));
	ad=&jpg_file[num];
#else
    FILE *fp_handle;
	fp_handle= fopen("/mnt/uda1/ad_jpg.jpg", "rb");
    if(fp_handle == NULL)
    {
        AD_IMG_PRINTF(" fb_handle is null\n");
        return;
    }

	AD_IMG_PRINTF("fp_handle=%x\n",fp_handle);
    UINT32 readsize=0;
    num %= (sizeof(jpg_file)/sizeof(ad));
    ad=&jpg_file[num];
	len=264*1024;
	logo_buf = (UINT8 *)MALLOC(len);

	readsize=fread(logo_buf,1,len,fp_handle);/*actual read file bytes*/
	AD_IMG_PRINTF("readsize=%d\n",readsize);
	AD_IMG_PRINTF("logo_buf=%x\n",logo_buf);
    ad->rect.uLeft=0;
	ad->rect.uTop=0;
	ad->rect.uHeight=240;
	ad->rect.uWidth=360;

#endif

	ad_pic_img_draw(logo_buf, len, &(ad->rect));
	//ad_pic_img_draw((UINT8 *)ad->buf, ad->len, &(ad->rect));
	FREE(logo_buf);
}

static ad bmp_file[1] =
{
	{
		0,
		(UINT8 *)test_sample,
		sizeof(test_sample),
		{0,0,720,576}
	},

};
void show_bmp_pic(UINT8 num)
{
	ad *ad = NULL;
	struct sto_device *sto_flash_dev;
	UINT8 *logo_buf;
	UINT32 addr,len;


#if 1
	FILE *fp_handle;
	fp_handle= fopen("/mnt/uda1/ad_bmp.bmp", "rb");
    if(fp_handle == NULL)
    {
        AD_IMG_PRINTF(" fb_handle is null\n");
        return;
    }

	AD_IMG_PRINTF("fp_handle=%x\n",fp_handle);
#else
	if(api_get_chunk_add_len(0x0AF50400,&addr,&len) == 0) 	//bmp chunk id
	{
        AD_IMG_PRINTF("api_get_chunk_add_len error.\n");
        return;
	}
#endif

	UINT32 readsize=0;
	len=264*1024;
	logo_buf = (UINT8 *)MALLOC(len);

	readsize=fread(logo_buf,1,len,fp_handle);/*actual read file bytes*/
	AD_IMG_PRINTF("readsize=%d\n",readsize);
	AD_IMG_PRINTF("logo_buf=%x\n",logo_buf);
#if 0
	sto_flash_dev = (struct sto_device *)dev_get_by_id(HLD_DEV_TYPE_STO, 0);
	sto_get_data(sto_flash_dev, (UINT8 *)logo_buf, addr, len);
#endif
	num %= (sizeof(bmp_file)/sizeof(ad));
	ad=&bmp_file[num];


#if 1
 	ad->rect.uLeft=0;
	ad->rect.uTop=0;
	ad->rect.uHeight=300;
	ad->rect.uWidth=300;
#endif


	ad_pic_img_draw(logo_buf, len, &(ad->rect));
    FREE(logo_buf);
}
//#endif
//#endif
#endif


#ifdef PIP_PNG_GIF

/************************************************************
 * brief:     feature support , osd display picture 
 * detail:    big file read, decode file and fix the window 
 *            size, and give the examle
 * author:    saicheong.yuen
 * date:      2014-7-14
 *************************************************************/

/* macro to config file operation. memory or pe cache */
//#define     AP_PIC_FILE_MEMOP
//#define     AP_PIC_PECACHE_MALLOC
//#define     AP_PIC_OUTBUF_MALLOC

#ifdef      AP_PIC_FILE_MEMOP
#undef      AP_PIC_PECACHE_MALLOC
#endif

/* memory address mapping to decode image file */
#define     AP_PIC_BUF_DECODEADDR  (UINT8 *)((__MM_MP_BUFFER_ADDR+0x10000) & ~(3<<29))
#define     AP_PIC_BUF_DECODELEN   0x500000
#define     AP_PIC_BUF_BITMAPADDR  (UINT8 *)(AP_PIC_BUF_DECODEADDR + AP_PIC_BUF_DECODELEN)
#ifdef      AP_PIC_OUTBUF_MALLOC
  #define   AP_PIC_BUF_BITMAPLEN   0
#else
  #define   AP_PIC_BUF_BITMAPLEN   0x100000
#endif
#define     AP_PIC_BUF_FILEADDR    (UINT8 *)(AP_PIC_BUF_BITMAPADDR + AP_PIC_BUF_BITMAPLEN)
#ifdef      AP_PIC_PECACHE_MALLOC
  #define   AP_PIC_BUF_FILELEN     0
#else
  #define   AP_PIC_BUF_FILELEN     0x100000
#endif



/************************************************************
 *  read image file operation
 *  two method:
 *  1. pe cache
 *  2. memory -- this just read file in the memory
 *************************************************************/
#define AP_PIC_SUCCESS          0
#define AP_PIC_FAIL             -1


#define AP_PIC_PECACHE_BLK_SIZE (64*1024)
#define AP_PIC_PECACHE_IMG_SIZE (AP_PIC_PECACHE_BLK_SIZE*2)

static int ad_pic_fop_pecache_open(file_h fh, const char* filename);
static int ad_pic_fop_pecache_close(file_h fh);
static int ad_pic_fop_pecache_read(file_h fh, BYTE *buf, UINT32 size);
static int ad_pic_fop_pecache_seek(file_h fh, long offset, UINT32 origin);

static int ad_pic_fop_mem_open(file_h fh, const char* filename);
static int ad_pic_fop_mem_close(file_h fh);
static int ad_pic_fop_mem_read(file_h fh, BYTE *buf, UINT32 size);
static int ad_pic_fop_mem_seek(file_h fh, long offset, UINT32 origin);

typedef struct ad_pic_fop_s
{
    int (*file_open)(file_h fh, const char* filename);
    int (*file_close)(file_h fh);
    int (*file_read)(file_h fh, BYTE *buf, UINT32 size);
    int (*file_seek)(file_h fh, long offset, UINT32 origin);
} ad_pic_fop_t;

typedef struct ad_pic_fhdl_s
{
    int           valid;
    int           pecache_id;
    UINT8         *pecache_buf;
    FILE          *mem_fp;  
    UINT8         *mem_addr;
    INT32         mem_pos;
    UINT32        mem_filesz;
    ad_pic_fop_t  *fop;
} ad_pic_fhdl_t;

ad_pic_fop_t ad_pic_fop_pecache =
{
    ad_pic_fop_pecache_open,
    ad_pic_fop_pecache_close,
    ad_pic_fop_pecache_read,
    ad_pic_fop_pecache_seek
};

ad_pic_fop_t ad_pic_fop_mem =
{
    ad_pic_fop_mem_open,
    ad_pic_fop_mem_close,
    ad_pic_fop_mem_read,
    ad_pic_fop_mem_seek
};

ad_pic_fhdl_t     g_ad_pic_fhdls[2];
/* 0 is reserved. 0 is unable to be used. */
#define           AD_PIC_HDL_ALLOC   1


/************************************************************
 *  read image file by pe cache operation. implementer.
 *************************************************************/

/* file operation implementer: open, using pe cache.*/
static int ad_pic_fop_pecache_open(file_h fh, const char* filename)
{
    int   pecache_id = -1;
    UINT8 *pecache_buf = NULL;
    ad_pic_fhdl_t *phdl;
    phdl = &g_ad_pic_fhdls[fh];

#ifdef AP_PIC_PECACHE_MALLOC
    pecache_buf = MALLOC(AP_PIC_PECACHE_IMG_SIZE);
    if (pecache_buf == NULL)
    {
       libc_printf("%s %d: malloc fail\n", __FILE__, __LINE__);
       return AP_PIC_FAIL;
    }
    pecache_id = pe_cache_open(filename, phdl->pecache_buf, AP_PIC_PECACHE_IMG_SIZE, AP_PIC_PECACHE_BLK_SIZE);

#else
    pecache_buf = AP_PIC_BUF_FILEADDR;
    phdl->pecache_buf = pecache_buf;
    pecache_id = pe_cache_open(filename, phdl->pecache_buf, AP_PIC_BUF_FILELEN, AP_PIC_PECACHE_BLK_SIZE);
#endif
    if (pecache_id < 0)
    {
#ifdef AP_PIC_PECACHE_MALLOC  
        FREE(phdl->pecache_buf);
        phdl->pecache_buf = NULL;
#endif
        libc_printf("%s %d: pecache_id fail\n", __FILE__, __LINE__);
        return AP_PIC_FAIL;
    }

    phdl->pecache_id = pecache_id;
    return AP_PIC_SUCCESS;
}

/* file operation implementer: close, using pe cache.*/
static int ad_pic_fop_pecache_close(file_h fh)
{
    ad_pic_fhdl_t *phdl;
    phdl = &g_ad_pic_fhdls[fh];

    pe_cache_close(phdl->pecache_id);
    phdl->pecache_id = -1;

#ifdef AP_PIC_PECACHE_MALLOC
    if (phdl->pecache_buf)
    {
        FREE(phdl->pecache_buf);
        phdl->pecache_buf = NULL;
    }
#endif

    return AP_PIC_SUCCESS;
}

/* file operation implementer: read, using pe cache.*/
static int ad_pic_fop_pecache_read(file_h fh, BYTE *buf, UINT32 size)
{
    UINT32        ret = 0;
    int           pecache_id;
    ad_pic_fhdl_t *phdl;

    phdl = &g_ad_pic_fhdls[fh];

    if (size == 0)
        return 0;

    pecache_id = phdl->pecache_id;
 
    if (pecache_id < 0)
    {
        libc_printf("%s(): read pecache fail!!!\n", __FUNCTION__);
        return 0;
    }

    do 
    {
        ret = pe_cache_read(pecache_id, buf, size, 0xFFFFFFFF);
        if ((ret > 0) && (ret <= size))
        {
            break;
        }
        else if(ret > size)
        {
            ret = 0;
            break;
        }
        if (pe_cache_check_eof(pecache_id)) 
        {
            break;
        }
        osal_task_sleep(100);
    } while(ret == 0);
    
    return (int)ret;
}

/* file operation implementer: seek, using pe cache.*/
static int ad_pic_fop_pecache_seek(file_h fh, long offset, UINT32 origin)
{
    int           ret = 0;
    int           pecache_id;
    ad_pic_fhdl_t *phdl;

    phdl = &g_ad_pic_fhdls[fh];

    pecache_id = phdl->pecache_id;
    if (pecache_id < 0)
        return AP_PIC_FAIL;

    ret = pe_cache_seek(pecache_id, (off_t)offset, origin);
    if (ret == AP_PIC_FAIL)
    {
        libc_printf("%s(): seek pecache fail!!!\n", __FUNCTION__);
        return AP_PIC_FAIL;
    }

    return AP_PIC_SUCCESS;

}

/************************************************************
 *  read image file by memory operation. implementer.
 *************************************************************/
/* file operation implementer: open, using mem.*/
static int ad_pic_fop_mem_open(file_h fh, const char* filename)
{
    ad_pic_fhdl_t *phdl;

    phdl = &g_ad_pic_fhdls[fh];

    UINT32 readsize=0;
    phdl->mem_fp = fopen(filename, "rb");
    if(phdl->mem_fp == NULL)
    {
        AD_IMG_PRINTF(" file handle is null\n");
        return AP_PIC_FAIL;
    }

    phdl->mem_addr = AP_PIC_BUF_FILEADDR;

    phdl->mem_filesz = fread(phdl->mem_addr, 1, AP_PIC_BUF_FILELEN, phdl->mem_fp);
    if ((0 == phdl->mem_filesz) || (AP_PIC_BUF_FILELEN == phdl->mem_filesz))
    {
        AD_IMG_PRINTF(" file size is zero or too big!\n");
        return AP_PIC_FAIL;
    }
    AD_IMG_PRINTF(" file size is %d\n",  phdl->mem_filesz);
    phdl->mem_pos = 0;

    return AP_PIC_SUCCESS;
};

/* file operation implementer: close, using mem.*/
static int ad_pic_fop_mem_close(file_h fh)
{
    ad_pic_fhdl_t *phdl;
    
    phdl = &g_ad_pic_fhdls[fh];

    fclose(phdl->mem_fp);
    return 0;
};

/* file operation implementer: read, using mem.*/
static int ad_pic_fop_mem_read(file_h fh, BYTE *buf, UINT32 size)
{
	UINT32 read_pos;
	UINT32 read_len;
    ad_pic_fhdl_t *phdl;
    
    phdl = &g_ad_pic_fhdls[fh];

	read_pos = phdl->mem_pos+size;
	if(read_pos > phdl->mem_filesz)
	{
		read_len = phdl->mem_filesz - phdl->mem_pos;
		MEMCPY((void *)buf, (void *)(phdl->mem_addr + phdl->mem_pos), read_len);
		phdl->mem_pos += read_len;
		return read_len;
	}
	else
	{
		MEMCPY((void *)buf, (void *)(phdl->mem_addr + phdl->mem_pos), size);
		phdl->mem_pos += size;
		return size;
	}
};

/* file operation implementer: seek, using mem.*/
static int ad_pic_fop_mem_seek(file_h fh, long offset, UINT32 origin)
{
    ad_pic_fhdl_t *phdl;
        
    phdl = &g_ad_pic_fhdls[fh];

	if(origin == 0)
	{
		phdl->mem_pos = (UINT32)offset;
		return AP_PIC_SUCCESS;
	}
	return AP_PIC_FAIL;
};

/************************************************************
 *  bind the file handle and driver. adapter.
 *************************************************************/

/* file operation adapter: read */
int ad_pic_file_read(file_h fh, BYTE *buf, UINT32 size)
{
    ad_pic_fhdl_t *phdl;
    phdl = &g_ad_pic_fhdls[fh];

    return  phdl->fop->file_read(fh, buf, size);
}

/* file operation adapter: seek */
int ad_pic_file_seek(file_h fh, long offset, UINT32 origin)
{
    ad_pic_fhdl_t *phdl;
    phdl = &g_ad_pic_fhdls[fh];

    return phdl->fop->file_seek(fh, offset, origin);
}

/* file operation adapter: open */
int ad_pic_file_init(file_h *fh, const char* filename)
{
    int ret;
    ad_pic_fhdl_t *phdl;
    phdl = &g_ad_pic_fhdls[AD_PIC_HDL_ALLOC];

#ifdef AP_PIC_FILE_MEMOP
    phdl->fop = &ad_pic_fop_mem;
#else
    phdl->fop = &ad_pic_fop_pecache;
#endif

    ret = phdl->fop->file_open((file_h)AD_PIC_HDL_ALLOC, filename);
    if (AP_PIC_SUCCESS != ret)
    {
        libc_printf("%s %d: open file failed\n", __FILE__, __LINE__);
        return AP_PIC_FAIL;
    }

    phdl->valid = 1;
    *fh = AD_PIC_HDL_ALLOC;
    return AP_PIC_SUCCESS;
}

/* file operation adapter: close */
int ad_pic_file_exit(file_h fh)
{
    int ret;
    ad_pic_fhdl_t *phdl;
    phdl = &g_ad_pic_fhdls[fh];

    ret = phdl->fop->file_close(fh);
    if (AP_PIC_SUCCESS != ret)
        return AP_PIC_FAIL;    

    phdl->valid = 0;
    return AP_PIC_SUCCESS;
}

/************************************************************
 *  decode the image file. 
 *************************************************************/
/* low osd callback function, just update the picture rectangle area. */
static void ad_pic_update_cb(void *handle, pImagedec_Out_Image pimage, struct Rect *rect)
{
    struct Rect *dst_rect;
    dst_rect = (struct Rect*) handle;
    dst_rect->uStartX = rect->uStartX;
    dst_rect->uStartY = rect->uStartY;
    dst_rect->uWidth  = rect->uWidth;
    dst_rect->uHeight = rect->uHeight;	
}

/* decode the image file and buffer it. */
int ad_pic_file_decode(file_h fh, UINT8 *deccode_buf, INT32 deccode_buflen, UINT8 *bitmap_buf, INT32 bitmap_buflen, struct Rect *src_rect, struct Rect *dst_rect)
{
    BOOL    ret = 0;
    INT32   bitmap_pic_len = 0;

    if ((NULL == deccode_buf) || (NULL == bitmap_buf) || (NULL == src_rect) || (NULL == dst_rect))
    {
        AD_IMG_PRINTF("%s() pointer parameter is NULL!\n", __FUNCTION__);
        return AP_PIC_FAIL;
    }

    bitmap_pic_len = (INT32)((INT32)src_rect->uWidth * (INT32)src_rect->uHeight) * 4;
    if (bitmap_buflen < bitmap_pic_len)
    {
        AD_IMG_PRINTF("%s() buffer size if too small, may lead to problem!\n", __FUNCTION__);
        return AP_PIC_FAIL;
    }

    imagedec_id id = 0;

    /* initialize the decode buffer, and image file operations */
    Imagedec_Init_Config img_init_info;
    MEMSET(&img_init_info,0,sizeof(Imagedec_Init_Config));
    img_init_info.decoder_buf = deccode_buf;
    img_init_info.decoder_buf_len = deccode_buflen;
    img_init_info.fread_callback = ad_pic_file_read;
    img_init_info.fseek_callback = ad_pic_file_seek;

    id = imagedec_init(&img_init_info);
    AD_IMG_PRINTF("%s() imagedec_init id = (%d)!\n", __FUNCTION__, id);
    if (0 == id)
    {
        AD_IMG_PRINTF("%s() imagedec_init failed(%d)!\n", __FUNCTION__, id);
        return AP_PIC_FAIL;
    }

    /* configure the decoder. */
#ifdef DUAL_ENABLE
    ret = imagedec_ioctl_ex(id, IMAGEDEC_IO_CMD_OPEN_HW_ACCE, 0);
#else
    ret = imagedec_ioctl(id, IMAGEDEC_IO_CMD_OPEN_HW_ACCE, 0);
#endif
    if (TRUE != ret)
    {
        AD_IMG_PRINTF("%s() imagedec_ioctl(IMAGEDEC_IO_CMD_OPEN_HW_ACCE) failed!\n", __FUNCTION__);
        return AP_PIC_FAIL;
    }

    /* configure the decode system. */
    Imagedec_Mode_Par dec_par;
    MEMSET((void *)&dec_par,0,sizeof(Imagedec_Mode_Par));
    dec_par.vp_close_control = 0;
    dec_par.pro_show = 1;
    dec_par.dis_rect.uStartX = 0;
    dec_par.dis_rect.uStartY = 0;
    dec_par.dis_rect.uWidth = 720;
    dec_par.dis_rect.uHeight = 576;
    dec_par.src_rect.uStartX = 0;
    dec_par.src_rect.uStartY = 0;
    dec_par.src_rect.uWidth = 720;
    dec_par.src_rect.uHeight = 576;
    imagedec_set_mode(1, 1, &dec_par);

    /* configure the osd callback and output parameters. */
    Imagedec_Osd_Config config;
    MEMSET((void *)&config, 0, sizeof(Imagedec_Osd_Config));
    config.blt = ad_pic_update_cb;
    config.handle = ((void*)dst_rect);
    config.pic_frmt = 0;
    imagedec_osd_init(&config);


    /* configure the osd input parameters and buffer. */
    Imagedec_Osd_Io_Cmd cmd;
    MEMSET((void *)&cmd,0,sizeof(Imagedec_Osd_Io_Cmd));
    cmd.on = 1;
    cmd.bitmap_start = (UINT32)bitmap_buf;
    cmd.bitmap_size = bitmap_buflen;
    cmd.dis_rect.uStartX = src_rect->uStartX;
    cmd.dis_rect.uStartY = src_rect->uStartY;
    cmd.dis_rect.uWidth  = src_rect->uWidth;
    cmd.dis_rect.uHeight = src_rect->uHeight;
#ifdef DUAL_ENABLE
    imagedec_ioctl_ex(id, IMAGEDEC_IO_CMD_OSD_SHOW, (UINT32)&cmd);
#else
    imagedec_ioctl(id, IMAGEDEC_IO_CMD_OSD_SHOW, (UINT32)&cmd);
#endif

    /* decode. */
    ret = imagedec_decode(id, fh);
    if (ret != TRUE)
        AD_IMG_PRINTF("\n Decode Image Unsuccessfully");

    /* recycle the resouce. */
    if (imagedec_stop(id) != TRUE)
        AD_IMG_PRINTF("\n Stop Image decoding unsuccessfully!\n");
    if (imagedec_release(id) != TRUE)
        AD_IMG_PRINTF("\n Release Image decoder unsuccessfully!\n");   

    /* return. */
    if (ret != TRUE)
        return AP_PIC_FAIL;
    else
        return AP_PIC_SUCCESS;
}

/************************************************************
 *  the example to use api to show pic
 *  below belong to applicatin, they are not good enough 
 *  to be compliant with old system. 
 *************************************************************/

typedef struct app_ad_pic_data_s
{
    file_h         hdl_curr;
    UINT8          *deccode_buf;
    INT32          deccode_buflen;
    UINT8          *bitmap_buf;
    INT32          bitmap_buflen;
    struct Rect    src_rect;
    struct Rect    dst_rect;    
} app_ad_pic_data_t;

/* allocation resouce and configure. decode the image file and buffer it. */
int app_ad_pic_buffer(app_ad_pic_data_t *ppic_img_data, const char* file_name)
{
    int         ret = AP_PIC_SUCCESS;

    /* get the file handle. */
    ret = ad_pic_file_init(&(ppic_img_data->hdl_curr), file_name);
    if (AP_PIC_SUCCESS != ret)
    {
        AD_IMG_PRINTF("%s: file can't be opened!\n", __FUNCTION__);
        return AP_PIC_FAIL;  
    }

    /* configure the picture size and location. define the display area. */
    ppic_img_data->src_rect.uStartX = 0;
    ppic_img_data->src_rect.uStartY = 0;
    ppic_img_data->src_rect.uWidth  = 400;
    ppic_img_data->src_rect.uHeight = 300;

    /* the final picture size will fill dst_rect. fix the display area. */
    MEMSET((void *)&(ppic_img_data->dst_rect), 0, sizeof(struct OSDRect));

    /* decode buffer allocation. */
    ppic_img_data->deccode_buf = AP_PIC_BUF_DECODEADDR;
    ppic_img_data->deccode_buflen = AP_PIC_BUF_DECODELEN;

    /* picture buffer allocation. */
#ifdef AP_PIC_OUTBUF_MALLOC
    ppic_img_data->bitmap_buflen = (INT32)((INT32)(ppic_img_data->src_rect.uWidth) * (INT32)(ppic_img_data->src_rect.uHeight)) * 4;
    ppic_img_data->bitmap_buf = MALLOC(ppic_img_data->deccode_buflen);
    if (NULL == ppic_img_data->bitmap_buf)
    {
         ad_pic_file_exit(ppic_img_data->hdl_curr);
         AD_IMG_PRINTF("%s: alloc out buffer fail!\n", __FUNCTION__);
         return AP_PIC_FAIL;
    }
    MEMSET(ppic_img_data->bitmap_buf, 0, ppic_img_data->bitmap_buflen);
#else
    ppic_img_data->bitmap_buf = AP_PIC_BUF_BITMAPADDR;
    ppic_img_data->bitmap_buflen= AP_PIC_BUF_BITMAPLEN;
#endif

    /* decode the image file */
    ret = ad_pic_file_decode(ppic_img_data->hdl_curr, ppic_img_data->deccode_buf, ppic_img_data->deccode_buflen, 
        ppic_img_data->bitmap_buf, ppic_img_data->bitmap_buflen, &ppic_img_data->src_rect, &ppic_img_data->dst_rect);
    if (AP_PIC_SUCCESS != ret)
    {
#ifdef AP_PIC_OUTBUF_MALLOC
        FREE(ppic_img_data->bitmap_buf);
#endif
        ad_pic_file_exit(ppic_img_data->hdl_curr);
        AD_IMG_PRINTF("%s: decode image error!\n", __FUNCTION__);
        return AP_PIC_FAIL;
    }

    return AP_PIC_SUCCESS;
}

/* display the picture. refer the file_name as the path. */
int app_ad_pic_display(app_ad_pic_data_t *ppic_img_data, const char* file_name)
{
    int            ret = AP_PIC_SUCCESS;
    struct OSDRect draw_rect;

    /* decode and buffer the image */
    ret = app_ad_pic_buffer(ppic_img_data, file_name);
    if (AP_PIC_FAIL == ret)
    {
        AD_IMG_PRINTF("%s() : decode failed!\n", __FUNCTION__);
        return AP_PIC_FAIL;
    }
    AD_IMG_PRINTF("%s: decode finish!\n", __FUNCTION__);

    /* draw the picture by using ge */
    draw_rect.uLeft   = ppic_img_data->dst_rect.uStartX;
    draw_rect.uTop    = ppic_img_data->dst_rect.uStartY;
    draw_rect.uWidth  = ppic_img_data->dst_rect.uWidth;
    draw_rect.uHeight = ppic_img_data->dst_rect.uHeight;
    ad_pic_gfx_draw(&draw_rect, ppic_img_data->bitmap_buf);
    return AP_PIC_SUCCESS;
}

/* undisplay the picture. and recycle the resouces */
int app_ad_pic_undisplay(app_ad_pic_data_t *ppic_img_data)
{
    int ret = AP_PIC_SUCCESS;
    
    ad_pic_gif_close();
    ad_pic_png_close();
    ad_pic_img_close();
    OSD_ClearScreen();

#ifdef AP_PIC_OUTBUF_MALLOC
    FREE(ppic_img_data->bitmap_buf);
#endif
    ad_pic_file_exit(ppic_img_data->hdl_curr);
    if (AP_PIC_SUCCESS != ret)
        return AP_PIC_FAIL;    
    return 0;
}

/************************************************************
 *  application, display the picture by using reference path. 
 *************************************************************/

/* image file path */
const char* app_ad_pic_path[] = {
"/mnt/uda1/jpg/1.JPG",
"/mnt/uda1/jpg/2.JPG",
"/mnt/uda1/jpg/3.JPG",
"/mnt/uda1/jpg/4.JPG",
"/mnt/uda1/jpg/5.JPG"
};

typedef struct app_ad_pic_handle_tag{
    int pre;
    int curr;
    int display;
} app_ad_pic_handle_t;

typedef struct app_ad_pic_op_tag {
    int (*display) (app_ad_pic_data_t *ppic_img_data, const char* file_name);
    int (*undisplay) (app_ad_pic_data_t *ppic_img_data);
} app_ad_pic_op_t;

app_ad_pic_op_t app_ad_pic_op_simple = {
    app_ad_pic_display,
    app_ad_pic_undisplay
};

app_ad_pic_handle_t      g_app_ad_pic_handle = {0, 0, 0};
app_ad_pic_op_t         *g_app_ad_pic_op = NULL;
app_ad_pic_data_t        g_app_ad_pic_data;

#include "win_com_popup.h"

/* popup menu */
int app_ad_pic_popup(char *info)
{

    UINT8 back_save;
    win_compopup_smsg_restoreback();
    win_compopup_init(WIN_POPUP_TYPE_SMSG);
    
    win_compopup_set_msg(info, NULL, 0);
    win_compopup_set_frame(0, 320, 400, 100);
    win_compopup_open_ext(&back_save);
    return 0;
}

/* select the file path */
int app_ad_pic_select()
{
    int mod = 1;
    mod = sizeof(app_ad_pic_path) / sizeof(const char*);
    char info[64];
 
    g_app_ad_pic_handle.curr++;
    g_app_ad_pic_handle.curr %= mod;

    AD_IMG_PRINTF("%s(): index=%d path=%s....\n", __FUNCTION__, g_app_ad_pic_handle.curr, app_ad_pic_path[g_app_ad_pic_handle.curr]);

    if (g_app_ad_pic_handle.curr == g_app_ad_pic_handle.pre){
        sprintf(info, "clear?");
    } else {
        sprintf(info, "?? %s", app_ad_pic_path[g_app_ad_pic_handle.curr]);
    }

    app_ad_pic_popup(info);
    return AP_PIC_SUCCESS;
}

/* display and undisplay the picture */
int app_ad_pic_action()
{
    int ret = AP_PIC_SUCCESS;

    /* initialize the display/undisplay operation */
    if (NULL == g_app_ad_pic_op)
    {
        g_app_ad_pic_op=&app_ad_pic_op_simple;
    }

    /* when the osd is cleaned, just display the picture */
    if (FALSE == g_app_ad_pic_handle.display)
    {
        app_ad_pic_popup("waiting..");
        ret = g_app_ad_pic_op->display(&g_app_ad_pic_data, app_ad_pic_path[g_app_ad_pic_handle.curr]);
        if (AP_PIC_SUCCESS != ret)
        {
            app_ad_pic_popup("ERROR!");
            return ret;
        }
        app_ad_pic_popup("OK!");
        g_app_ad_pic_handle.pre = g_app_ad_pic_handle.curr;
        g_app_ad_pic_handle.display = TRUE;
        return AP_PIC_SUCCESS;
    }

    /* the picture is displayed. when other picture isn't selected, so undisplay and clear osd. */
    if (g_app_ad_pic_handle.curr == g_app_ad_pic_handle.pre)
    {
        app_ad_pic_popup("prepare to clear!");
        osal_task_sleep(1000);
        win_compopup_smsg_restoreback();
        ret = g_app_ad_pic_op->undisplay(&g_app_ad_pic_data);
        if (AP_PIC_SUCCESS != ret)
        {
            return ret;
        }
        g_app_ad_pic_handle.display = FALSE;
        return AP_PIC_SUCCESS;
    /* the picture is displayed. when other picture is selected, so display other picture. */
    } else {
        ret = g_app_ad_pic_op->undisplay(&g_app_ad_pic_data);
        if (AP_PIC_SUCCESS != ret)
        {
            return ret;
        }
        g_app_ad_pic_handle.display = FALSE;
        app_ad_pic_popup("waiting..");
        ret = g_app_ad_pic_op->display(&g_app_ad_pic_data, app_ad_pic_path[g_app_ad_pic_handle.curr]);
        if (AP_PIC_SUCCESS != ret)
        {
            app_ad_pic_popup("ERROR!");
            return ret;
        }
        app_ad_pic_popup("OK!");
        g_app_ad_pic_handle.pre = g_app_ad_pic_handle.curr;
        g_app_ad_pic_handle.display = TRUE;
        return AP_PIC_SUCCESS;
    }

    return AP_PIC_SUCCESS;
}
#endif

